package client

import (
	"sync"
	"cloud_worm/access/server/rpcclient"
	"cloud_worm/util/proto/urpc"
	"cloud_worm/util/umodels/mysqldb/dbmanager"
	"github.com/golang/glog"
)

func (p *AgentPool) HaveConnByIP(ip string) bool {
	p.Mux.Lock()
	_, exist := p.IPMap[ip]
	p.Mux.Unlock()
	return exist
}

func (p *AgentPool) HaveConnByID(id string) bool {
	p.Mux.Lock()
	_, exist := p.IdMap[id]
	p.Mux.Unlock()
	return exist
}

func (p *AgentPool) NewConnByIP(agent *Agent)  {
	p.Mux.Lock()
	p.IPMap[agent.IP] = agent				// 半链接时，先加入ip的map中
	p.Mux.Unlock()
	return
}

func (p *AgentPool) AddAgent(agent *Agent)  {

	p.Mux.Lock()

	p.IPMap[agent.IP] = agent
	p.IdMap[agent.Id] = agent				// 认证完成时，加入到id的map中

	p.Mux.Unlock()

	return
}

func (p *AgentPool) DelAgent(agent *Agent)  {

	hasLogin := false
	// 释放连接资源
	p.Mux.Lock()
	if _, exist := p.IPMap[agent.IP]; exist {
		delete(p.IPMap, agent.IP)
	}
	if _, exist := p.IdMap[agent.Id]; exist {
		hasLogin = true
		delete(p.IdMap, agent.Id)
	}

	agent.Connection.Close()
	p.Mux.Unlock()

	if hasLogin {
		wormId := &dbmanager.WormId{}
		if err := wormId.SetAgentOffline(agent.Id, agent.Version); err != nil {
			glog.Errorf("set agent'%s' offline err: %s", agent.IP, err.Error())
		}

		// 通知操作
		postData := &rpcclient.AgentEvent{
			EventType: urpc.AgentEventOffline,
			AgentId: agent.Id,
			AgentIP: agent.IP,
			Version: agent.Version,
		}
		rpcclient.PushClient.PushOneC <- postData
	}

	p.AgentFree.Put(agent)

	return
}

func (p *AgentPool) GetAgentByIP(ip string) *Agent {
	p.Mux.Lock()
	agent := p.IPMap[ip]
	p.Mux.Unlock()

	return agent
}

func (p *AgentPool) GetAgentByID(id string) *Agent {
	p.Mux.Lock()
	agent := p.IdMap[id]
	p.Mux.Unlock()

	return agent
}

type AgentPool struct {
	Mux 		sync.Mutex
	IPMap 		map[string]*Agent
	IdMap 		map[string]*Agent

	AgentFree 	sync.Pool
}

var AgentPoolInst *AgentPool
var agentOnce sync.Once

func init()  {
	agentOnce.Do(func() {
		AgentPoolInst = &AgentPool{
			IPMap: make(map[string]*Agent),
			IdMap: make(map[string]*Agent),

			AgentFree: sync.Pool{
				New: func() interface{} {
					return &Agent{
						CmdChanMap: make(map[string]chan interface{}),
					}
				},
			},
		}
	})
}


